--[[
  杭州银行 - 直销银行app
]]
require("apm_core")
local ApmJson = require("ApmJson")
local ApmExt = require("ApmExt")
local Base64 = require("Base64")
require("extension")

local G_DEBUG = true

if G_DEBUG == false then
    function logDebug(fmt,...) end
    function logInfo(fmt,...) end
    function logWarn(fmt,...) end
    function logError(fmt,...) end
    function logFatal(fmt,...) end
end

local KRED='\x1B[0;31m'
local KSALMON='\x1B[1;31m'
local KGREEN='\x1B[0;32m'
local KLIMEGREEN='\x1B[1;32m'
local KYELLOW='\x1B[0;33m'
local KORANGE='\x1B[0;34m'
local KBLUE='\x1B[1;34m'
local KMAGENTA='\x1B[0;35m'
local KPINK='\x1B[1;35m'
local KCYAN='\x1B[0;36m'
local RESET='\x1B[0m'

local t_xml_tree
local t_json_tree
local s_channel
local s_channel_name
local s_flowno
local s_rspcode
local s_rspmsg

local KEY_FILE = "../conf/certs/hzbankrsa.key"
local AES_IV = "JSNXSJYHJSNXSJYH"
local s_key_source
local u_rsa_key

local function detect_resp(s_payload)
    if s_payload == nil then return false end
    t_json_tree = ApmJson.decode(s_payload)
    return t_json_tree ~= nil
end

--- 解析响应
-- return
-- true: 解析成功; false: 解析失败
local function parse_resp()
    -- 交易返回码
    s_rspcode = t_json_tree.retCode
    if s_rspcode == nil then
        s_rspcode = t_json_tree.errorCode
    end

    -- 交易返回信息
    s_rspmsg = t_json_tree.retMsg
    if s_rspmsg == nil then
        s_rspmsg = t_json_tree.errorMessage
    end
    if s_rspmsg == nil then
        s_rspmsg = t_json_tree.result
        if s_rspmsg ~= nil then
            -- {"result":"success"}
            if s_rspmsg == "success" then
                s_rspcode = "0"
            else
                -- 这里是手动设的，正常应该看非success时是否带其他字段
                s_rspcode = "1"
            end
        end
    end
    return true
end

local function read_key_file(filename)
    local f = io.open(filename, 'r')
    if f == nil then return nil end
    local string = f:read("*all")
    f:close()
    return string
end

local function http_request_decrypt(s_httpbody)
    if s_httpbody == nil or s_httpbody == '' then return nil end

    if s_key_source == nil then
        s_key_source = read_key_file(KEY_FILE)
    end
    if s_key_source == nil or s_key_source == '' then
--        logError("key source is nil")
        return nil
    end

    local t = string.split(s_httpbody, string.char(29))
    if #t ~= 3 then return nil end
    if t[2] == nil or t[2] == '' then return nil end
    local s_data_base64_decoded = Base64.decode(t[2])
    if s_data_base64_decoded == nil or s_data_base64_decoded == '' then return nil end

    if t[3] == nil or t[3] == '' then return nil end
    local s_key_base64_decoded = Base64.decode(t[3])
    if s_key_base64_decoded == nil or s_key_base64_decoded == '' then return nil end

    if u_rsa_key == nil then
        u_rsa_key = ApmExt.PEMReadBIORSAPrivateKey(s_key_source)
        logInfo("u_rsa_key:[%s]", u_rsa_key)
    end
    if u_rsa_key == nil then
        logError("rsa key is nil")
        return nil
    end

    local s_aes_key = ApmExt.RSAPrivateDecrypt(s_key_base64_decoded, u_rsa_key)
--    logInfo(KYELLOW .. "AES_KEY:[%s]" .. RESET, s_aes_key)
    return ApmExt.AESCBCDecrypt(s_data_base64_decoded, string.len(s_data_base64_decoded), s_aes_key, AES_IV, 128)
end

function post_analysis()
    local ApmData = require("ApmData")
    if ApmData.getL7Proto() ~= 80 then return end
    if ApmData.getMsgType() ~= 1 then return end

    local url = ApmData.getField("transaction.title", 1)
    if url == nil then return end

    local s_req = ApmData.getField("request.http.body.1", 1)
    local s_decrypted = http_request_decrypt(s_req)
    if s_decrypted ~= nil then
        --        logInfo(KGREEN .. "DECRYPTED_DATA:[%s]" .. RESET, s_decrypted)
        ApmData.replaceField("request.http.body.1", s_decrypted)
    end

    -- 交易类型
    local _, _, s_transtype = string.find(url, "/(%a+)$")
    if s_transtype == nil then return end
    local s_transtype_name = s_transtype

    local s_resp = ApmData.getField("response.http.body.1", 1)
    if s_resp ~= nil then
        s_resp = string.trim(s_resp)
        if detect_resp(s_resp) then
            parse_resp()
        end
    end

    ApmData.replaceField("transaction.type_code", s_transtype)
    ApmData.replaceField("transaction.type_name", s_transtype_name)

    if s_channel ~= nil then
        ApmData.replaceField("transaction.channel_code", s_channel)
        ApmData.replaceField("transaction.channel_name", s_channel_name)
    end

    if s_flowno ~= nil then
        ApmData.replaceField("transaction.code", s_flowno)
    end

    if s_rspcode ~= nil then
        ApmData.replaceField("response.code_string", s_rspcode)
        ApmData.delFields("response.code")
    end

    if s_rspmsg ~= nil then
        ApmData.replaceField("response.error_message", s_rspmsg)
    end

    -- 为了降低ES的压力，返回码正常的情况下删除body内容
--    if s_rspcode ~= "0" and s_rspcode ~= "00" and s_rspcode ~= "000000" then
--        ApmData.delFields("request.http.body.1")
--        ApmData.delFields("response.http.body.1")
--    end

    logInfo("直销APP(%s:%d->%s:%d) name:%s|channel:%s|seq:%s|ret:%s|%s",
        ApmData.getSrcIp(),
        ApmData.getSrcPort(),
        ApmData.getDstIp(),
        ApmData.getDstPort(),
        s_transtype_name,
        s_channel_name,
        s_flowno,
        s_rspcode,
        s_rspmsg
    )
    return
end
--直销银行app
--192.168.67.161:8809
--192.168.67.160:8809
--192.168.67.164:8809
--v1.0.3
